﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using __Able.Network.Utils;
using __Able.Network.RequestPacket;
using __Able.Network.ReplyPacket;

namespace __Able.Network.Packets
{
    public class _BasicFamilyParser : IParser
    {
        private int offset;
        private int length;

        private PacketHistory history;

        public _BasicFamilyParser()
        {
            history = new PacketHistory();
        }

        public bool Accept(ByteBuffer buf)
        {
            //保存偏移
            offset = buf.Position;
            int bufferLength = buf.Remaining();
            if (bufferLength <= 0)
                return false;
            bool accept = CheckTcp(buf);
            if (!accept)
                accept = CheckUdp(buf);
            return accept;
        }
        /// <summary>
        /// 检查一个包是否是udp包
        /// param buf ByteBuffer
        /// return true表示是，false表示否
        /// </summary>
        /// <param name="buf"></param>
        /// <returns></returns>
        private bool CheckUdp(ByteBuffer buf)
        {
            if ((_HeaderFamily)buf.Get(offset) == _HeaderFamily.HEADER_BASIC_FAMILY)
            {
                // 首先检查是否UDP方式
                length = buf.Length - buf.Position;
                if ((_TailFamily)buf.Get(offset + length - 1) == _TailFamily.TAIL_BASIC_FAMILY)
                    return true;
            }
            return false;
        }
        /// <summary>
        /// 检查一个包是否是tcp包
        /// param buf ByteBuffer
        /// return true表示是
        /// </summary>
        /// <param name="buf"></param>
        /// <returns></returns>
        private bool CheckTcp(ByteBuffer buf)
        {

            //buffer length不大于2则连个长度字段都没有
            int bufferLength = buf.Length - buf.Position;
            if (bufferLength < 2) return false;
            // 如果可读内容小于包长，则这个包还没收完
            length = buf.GetChar(offset);
            if (length <= 0 || length > bufferLength)
                return false;
            // 再检查包头包尾
            if ((_HeaderFamily)buf.Get(offset + 2) == _HeaderFamily.HEADER_BASIC_FAMILY)
                if ((_TailFamily)buf.Get(offset + length - 1) == _TailFamily.TAIL_BASIC_FAMILY)
                    return true;
            return false;

        }

        public int GetLength(ByteBuffer buf)
        {
            return length;
        }

        public bool IsDuplicate(_InPacket inpacket)
        {
            return history.Check(inpacket, true);
        }
        /// <summary>
        /// 得到包的命令和序号
        /// </summary>
        /// <param name="buf"></param>
        /// <param name="user"></param>
        /// <returns></returns>
        private _Command GetCommand(ByteBuffer buf, User user)
        {
            if (!user.IsUdp)
            {
                return (_Command)buf.GetUShort(offset + 5);
            }
            else
            {
                return (_Command)buf.GetUShort(offset + 3);
            }
        }

        public _InPacket ParseIncoming(ByteBuffer buf, int len, User user)
        {
            try
            {
                switch (GetCommand(buf, user))
                {
                    //case Command.QQ_CMD_SEARCH_USER:
                    //    return new SearchUserReplyPacket(buf, len, user);
                    //    return new FriendLevelOpReplyPacket(buf, len, user);
                    //case Command.QQ_CMD_SEND_SMS:
                    //    return new SendSMSReplyPacket(buf, len, user);
                    //case Command.QQ_CMD_TEMP_SESSION_OP:
                    //    return new TempSessionOpReplyPacket(buf, len, user);
                    //case Command.QQ_CMD_PRIVACY_DATA_OP:
                    //    return new PrivacyDataOpReplyPacket(buf, len, user);
                    default:
                        return new UnknownRequestPacket(buf, len, user);
                }
            }
            catch (PacketParseException e)
            {
                // 如果解析失败，返回null
                buf.Position = offset;
                return new UnknownRequestPacket(buf, len, user);
            }
        }

        public _OutPacket ParseOutcoming(ByteBuffer buf, int len, User user)
        {
            try
            {
                switch (GetCommand(buf, user))
                {
                    //case Command.QQ_CMD_TOUCH://由luna添加
                    //    //System.out.println("Touch包已经被发送");
                    //    return new _08TouchLoginPacket(buf, len, user);
                    default:
                        return new UnknownReplyPacket(buf, len, user);
                }
            }
            catch (PacketParseException e)
            {
                // 如果解析失败，返回一个未知包
                buf.Position = offset;
                return new UnknownReplyPacket(buf, len, user);
            }
        }

        public bool IsDuplicatedNeedReply(_InPacket inpackage)
        {
            return inpackage.Command == (ushort)_Command.CMD_GCCP;
        }

        public int Relocate(ByteBuffer buf)
        {
            int offset = buf.Position;
            if (buf.Remaining() < 2)
                return offset;
            int len = buf.GetUShort(offset);
            if (len <= 0 || offset + len > buf.Length)
                return offset;
            else
                return offset + len;
        }

        public PacketHistory GetHistory()
        {
            return history;
        }
    }
}
